/*
 * Records Package
 */
package edu.gatech.oad.records;
import edu.gatech.oad.user.Patient;
import edu.gatech.oad.user.User;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JLabel;
import javax.swing.BoxLayout;

import java.awt.Color;
import java.awt.Container;
//import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;

import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;


/**
 * Represents the viewing of an Invoice
 * @author Nathan Hurley
 * @version 1.0
 *
 */
public class InvoicePanel extends JPanel {

	/**
	 * Serialization
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * The current user
	 */
	private final User curUser;
	
	/**
	 * The current invoice
	 */
	private final Invoice curInvoice;
	
	/**
	 * Table that holds the data
	 */
	private final JTable costTable;
	
	/**
	 * Shows if invoice has been sent or paid
	 */
	private JLabel paid, sent;
	
	/**
	 * Table model
	 */
	private final DefaultTableModel tabModel;
	
	/**
	 * Panels within main panel
	 */
	private final JPanel invoiceInfo, buttonPanel;
	
	/**
	 * Buttons for editing and toggling Invoices isPaid and isSent variables
	 */
	private JButton editInvoice, changeIsPaid, changeIsSent;
	
	/**
	 * The size to add to the table
	 */
	private static final int TABLE_SIZE = 2;
	
	/**
	 * Number of decimal places
	 */
	private static final int NUM_DECIMAL = 2;
	
	/**
	 * Constructs an InvoicePanel to display an invoice
	 * @param curInvoice the current invoice to build around
	 * @param curUser the current user
	 */
	public InvoicePanel(Invoice curInvoice, User curUser){ // $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.constructorsOnlyInvokeFinalMethods
			this.curInvoice = curInvoice;
			this.curUser = curUser;
			tabModel = new DefaultTableModel();
			costTable = new JTable(tabModel);
			invoiceInfo = new JPanel();
			buttonPanel = new JPanel();
			prepareInvoiceInfo();//handles top panel for the Invoice info
			prepareInvoiceTable();//prepares the Table to display
			add(invoiceInfo);
			add(new JScrollPane(costTable));
			if(!(this.curUser instanceof Patient)){
				prepareButtonPanel();//prepares the buttons if needed
			}
			setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
	}
	
	/**
	 * Sets up the buttonPanel
	 */
	public final void prepareButtonPanel(){
		/*Create buttons and add listeners*/
		buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
		editInvoice = new JButton("Edit This Invoice");
		editInvoice.addActionListener(new ButtonListener());
		editInvoice.setAlignmentX(CENTER_ALIGNMENT);
		changeIsPaid = new JButton("Toggle Payment");
		changeIsPaid.addActionListener(new ButtonListener());
		changeIsSent = new JButton("Toggle Sent");
		changeIsSent.addActionListener(new ButtonListener());
		/*Add components to the buttonPanel*/
		buttonPanel.add(changeIsPaid);
		buttonPanel.add(editInvoice);
		buttonPanel.add(changeIsSent);
		add(buttonPanel);//add buttonPanel to main panel
	}
	
	/**
	 * Prepares the top panel that has the Invoices information
	 */
	public final void prepareInvoiceInfo(){
		paid = new JLabel();
		sent = new JLabel();
		/*Set layouts and add border*/
		invoiceInfo.setLayout(new BoxLayout(invoiceInfo, BoxLayout.Y_AXIS));
		invoiceInfo.setBorder(new TitledBorder("Invoice Information"));
		invoiceInfo.add(new JLabel("Patients Name: " 
				+ this.curInvoice.getAppointment().getPatient().getName()));
		invoiceInfo.add(new JLabel("Date of Appointment: " + this.curInvoice.getDate()));
		/*Check if bills have been paid or sent*/
		checkPaid();
		checkSent();
		/*Add to the invoiceInfo panel*/
		invoiceInfo.add(paid);
		invoiceInfo.add(sent);
		invoiceInfo.setAlignmentX(CENTER_ALIGNMENT);
	}
	
	/**
	 * Determines if the bill has been paid
	 */
	public final void checkPaid(){
		if(!curInvoice.equalIsPaid()){//case not paid
			paid.setText("This invoice hasn't been paid!");
			paid.setForeground(Color.red);
		}
		else{//bill has been paid
			paid.setText("This invoice has been paid");
			paid.setForeground(Color.blue);
		}
	}
	
	/**
	 * Determines if a bill has been sent
	 */
	public final void checkSent(){
		if(!curInvoice.equalIsSent()){//case not sent
			sent.setText("This invoice hasn't been sent!");
			sent.setForeground(Color.red);
		}
		else{//case sent
			sent.setText("This invoice has been sent");
			sent.setForeground(Color.blue);
		}
	}
	
	/**
	 * Sets up the invoice table
	 */
	public final void prepareInvoiceTable(){
		costTable.setTableHeader(null);
		final DecimalFormat costFormat = new DecimalFormat();
		costFormat.setMinimumFractionDigits(NUM_DECIMAL);
		costFormat.setMaximumFractionDigits(NUM_DECIMAL);
		tabModel.setColumnCount(TABLE_SIZE);
		tabModel.setRowCount(curInvoice.getTreatmentsBilled().size() + TABLE_SIZE);
		tabModel.setValueAt("<html><b>Treatment</b></html>", 0, 0);
		tabModel.setValueAt("<html><b>Cost</b></html>", 0, 1);
		int row = 1;
		for(Cost c : curInvoice.getTreatmentsBilled()){
			tabModel.setValueAt(c.getDescription(), row, 0);
			tabModel.setValueAt("$" + costFormat.format(c.getCost()), row, 1);
			row++;
		}
		tabModel.setValueAt("<html><b>Total Cost:</b></html>", 
				curInvoice.getTreatmentsBilled().size() + 1, 0);
		tabModel.setValueAt("<html><b>$" + costFormat.format(curInvoice.getCost()) 
				+ "</b></html>", curInvoice.getTreatmentsBilled().size() + 1, 1);
	}
	
	/**
	 * Listener for the edit and toggle buttons
	 * @author Nathan Hurley
	 */
	private class ButtonListener implements ActionListener{
		/**
		 * Toggles the isPaid and isSent and switches panels
		 * @param e the action that has just occurred
		 */
		public void actionPerformed(ActionEvent e){
			if(e.getSource() == changeIsPaid){//toggle isPaid // $codepro.audit.disable useEquals
				curInvoice.setIsPaid(!curInvoice.equalIsPaid());
				checkPaid();
			}
			else if(e.getSource() == changeIsSent){//toggle isSent // $codepro.audit.disable useEquals
				curInvoice.setIsSent(!curInvoice.equalIsSent());
				checkSent();
			}
			else{//switch to editing invoice panel
				final Container curContainer = buttonPanel.getParent();
				curContainer.removeAll();
				curContainer.add(new EditInvoicePanel(curInvoice, curUser));
				validate();
			}
		}
		
		/**
		 * @return String telling user which class this Listener belongs to
		 */
		public String toString(){
			return "Button Listener for the InvoicePanel class";
		}
	}
	
	/**
	 * @return the Invoice for this InvoicePanel 
	 */
	public Invoice getInvoice(){
		return curInvoice;
	}
	
	/**
	 * Checks if two InvoicePanels contain the same Invoice
	 * @return true if the two panels are equal false otherwise
	 * @param o the object to compare this to
	 */
	public boolean equals(Object o){
		if(this == o){
			return true;
		}
		if(o instanceof InvoicePanel){
			final InvoicePanel curPan = (InvoicePanel) o;
			if(curPan.getInvoice().equals(this.getInvoice())){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * @return the hashcode for the Invoice
	 */
	public int hashCode(){
		return getInvoice().hashCode();
	}
}
